// 数组响应式
function ArrayFunction () {
  const ARRAY_METHOD = ['push','pop','shift','unshift','reverse','sort','splice']
  const array_method = Object.create(Array.prototype)
  ARRAY_METHOD.forEach(method => {
    array_method[method] = function () {
      // 将数据进行响应式化
      Array.from(arguments).forEach(item => {
        observe(item)
      })
      // 把当前方法绑定到Array.prototype的原型上
      const res = Array.prototype[method].apply(this, arguments)
      return res
    }
  })
  return array_method
}
// 使数据响应化
function defineReactive (target, key, value, enumerable) {
  if (typeof value === 'object' && value !== null) {
    observe(value)
  }
  let dep = new Dep()
  // 查看时更直观，新增个属性
  dep.__propName__ = key
  Object.defineProperty(target, key, {
    enumerable: !!enumerable,
    configurable: true,
    get () {
      dep.depend()
      return value
    },
    set (newValue) {
      if ( value === newValue ) return
      if (typeof newValue === 'object' && newValue !== null) {
          observe(newValue)
        } else {
          value = newValue
        }
      // 派发更新, 找到全局的 watcher, 调用 update
      dep.notify()
    }
  })
}
// 对象响应化
function observe (data) {
  if (Array.isArray(data)) {
    data.__proto__ = ArrayFunction()
    data.forEach(item => {
      observe(item) // 递归
    })
  } else {
    Object.keys(data).forEach(key => {
      let value = data[key]
      defineReactive(data, key, value, true)
    })
  }
}
function proxy(target, data, key) {
  Object.defineProperty( target, key, {
    enumerable: true,
    configurable: true,
    get () {
      return target[data][key]
    },
    set (newVal) {
      target[data][key] = newVal
    }
  } )
}

Vue.prototype.initData = function () {
  // 响应式化
  observe(this._data)
  // 遍历 this._data 的成员, 将 属性转换为响应式 ( 上 ), 将 直接属性, 代理到 实例上
  Object.keys(this._data).forEach(key => {
    proxy( this, '_data', key)
  })
}